from typing import Dict, Iterator, List, Optional, Tuple, Type, Union

from OCC.Core.BRepTools import BRepTools_WireExplorer
from OCC.Core.GCPnts import (
    GCPnts_QuasiUniformDeflection,
    GCPnts_UniformAbscissa,
    GCPnts_UniformDeflection,
)
from OCC.Core.gp import gp_Dir, gp_Pnt
from OCC.Core.TopAbs import TopAbs_ShapeEnum
from OCC.Core.TopoDS import (
    TopoDS_CompSolid,
    TopoDS_Compound,
    TopoDS_Edge,
    TopoDS_Face,
    TopoDS_Shape,
    TopoDS_Shell,
    TopoDS_Solid,
    TopoDS_Vertex,
    TopoDS_Wire,
)

DISCRETIZATION_ALGORITHMS: Dict[
    str,
    Type[
        Union[
            GCPnts_UniformAbscissa,
            GCPnts_QuasiUniformDeflection,
            GCPnts_UniformDeflection,
        ]
    ],
]

def ordered_vertices_from_wire(wire: TopoDS_Wire) -> Iterator[TopoDS_Vertex]: ...
def ordered_edges_from_wire(wire: TopoDS_Wire) -> Iterator[TopoDS_Edge]: ...

class WireExplorer:
    wire: TopoDS_Wire
    wire_explorer: BRepTools_WireExplorer
    done: bool

    def __init__(self, wire: TopoDS_Wire) -> None: ...
    def ordered_edges(self) -> Iterator[TopoDS_Edge]: ...
    def ordered_vertices(self) -> Iterator[TopoDS_Vertex]: ...

class TopologyExplorer:
    my_shape: TopoDS_Shape
    ignore_orientation: bool
    topology_factory: Dict[TopAbs_ShapeEnum, Type[TopoDS_Shape]]

    def __init__(
        self, my_shape: TopoDS_Shape, ignore_orientation: Optional[bool] = True
    ) -> None: ...
    def faces(self) -> Iterator[TopoDS_Face]: ...
    def number_of_faces(self) -> int: ...
    def vertices(self) -> Iterator[TopoDS_Vertex]: ...
    def number_of_vertices(self) -> int: ...
    def edges(self) -> Iterator[TopoDS_Edge]: ...
    def number_of_edges(self) -> int: ...
    def wires(self) -> Iterator[TopoDS_Wire]: ...
    def number_of_wires(self) -> int: ...
    def shells(self) -> Iterator[TopoDS_Shell]: ...
    def number_of_shells(self) -> int: ...
    def solids(self) -> Iterator[TopoDS_Solid]: ...
    def number_of_solids(self) -> int: ...
    def comp_solids(self) -> Iterator[TopoDS_CompSolid]: ...
    def number_of_comp_solids(self) -> int: ...
    def compounds(self) -> Iterator[TopoDS_Compound]: ...
    def number_of_compounds(self) -> int: ...
    def number_of_ordered_vertices_from_wire(self, wire: TopoDS_Wire) -> int: ...
    def number_of_ordered_edges_from_wire(self, wire: TopoDS_Wire) -> int: ...
    def get_topology_summary(self) -> Dict[str, int]: ...
    def faces_from_edge(self, edge: TopoDS_Edge) -> Iterator[TopoDS_Face]: ...
    def number_of_faces_from_edge(self, edge: TopoDS_Edge) -> int: ...
    def edges_from_face(self, face: TopoDS_Face) -> Iterator[TopoDS_Edge]: ...
    def number_of_edges_from_face(self, face: TopoDS_Face) -> int: ...
    def vertices_from_edge(self, edge: TopoDS_Edge) -> Iterator[TopoDS_Vertex]: ...
    def number_of_vertices_from_edge(self, edge: TopoDS_Edge) -> int: ...
    def edges_from_vertex(self, vertex: TopoDS_Vertex) -> Iterator[TopoDS_Edge]: ...
    def number_of_edges_from_vertex(self, vertex: TopoDS_Vertex) -> int: ...
    def edges_from_wire(self, wire: TopoDS_Wire) -> Iterator[TopoDS_Edge]: ...
    def number_of_edges_from_wire(self, wire: TopoDS_Wire) -> int: ...
    def wires_from_edge(self, edg: TopoDS_Edge) -> Iterator[TopoDS_Wire]: ...
    def wires_from_vertex(self, edg: TopoDS_Vertex) -> Iterator[TopoDS_Wire]: ...
    def number_of_wires_from_edge(self, edg: TopoDS_Edge) -> int: ...
    def wires_from_face(self, face: TopoDS_Face) -> Iterator[TopoDS_Wire]: ...
    def number_of_wires_from_face(self, face: TopoDS_Face) -> int: ...
    def faces_from_wire(self, wire: TopoDS_Wire) -> Iterator[TopoDS_Face]: ...
    def number_of_faces_from_wires(self, wire: TopoDS_Wire) -> int: ...
    def faces_from_vertex(self, vertex: TopoDS_Vertex) -> Iterator[TopoDS_Face]: ...
    def number_of_faces_from_vertex(self, vertex: TopoDS_Vertex) -> int: ...
    def vertices_from_face(self, face: TopoDS_Face) -> Iterator[TopoDS_Vertex]: ...
    def number_of_vertices_from_face(self, face: TopoDS_Face) -> int: ...
    def solids_from_face(self, face: TopoDS_Face) -> Iterator[TopoDS_Solid]: ...
    def number_of_solids_from_face(self, face: TopoDS_Face) -> int: ...
    def faces_from_solids(self, solid: TopoDS_Solid) -> Iterator[TopoDS_Face]: ...
    def number_of_faces_from_solids(self, solid: TopoDS_Solid) -> int: ...
    def shells_from_face(self, face: TopoDS_Face) -> Iterator[TopoDS_Shell]: ...
    def number_of_shells_from_face(self, face: TopoDS_Face) -> int: ...
    def faces_from_shell(self, shell: TopoDS_Shell) -> Iterator[TopoDS_Face]: ...
    def number_of_faces_from_shell(self, shell: TopoDS_Shell) -> int: ...
    def solids_from_shell(self, shell: TopoDS_Shell) -> Iterator[TopoDS_Solid]: ...
    def number_of_solids_from_shell(self, shell: TopoDS_Shell) -> int: ...
    def shells_from_solid(self, solid: TopoDS_Solid) -> Iterator[TopoDS_Shell]: ...
    def number_of_shells_from_solid(self, solid: TopoDS_Solid) -> int: ...

def dump_topology_to_string(
    shape: TopoDS_Shape, level: Optional[int] = 0, buffer: Optional[str] = ""
) -> None: ...
def discretize_wire(
    a_wire: TopoDS_Wire,
    deflection: float = 0.5,
    algorithm: str = "QuasiUniformDeflection",
) -> List[gp_Pnt]: ...
def discretize_edge(
    a_edge: TopoDS_Edge,
    deflection: float = 0.2,
    algorithm: str = "QuasiUniformDeflection",
) -> List[Tuple[float, float, float]]: ...
def is_vertex(shape: TopoDS_Shape) -> bool: ...
def is_edge(shape: TopoDS_Shape) -> bool: ...
def is_wire(shape: TopoDS_Shape) -> bool: ...
def is_face(shape: TopoDS_Shape) -> bool: ...
def is_shell(shape: TopoDS_Shape) -> bool: ...
def is_solid(shape: TopoDS_Shape) -> bool: ...
def is_compound(shape: TopoDS_Shape) -> bool: ...
def is_compsolid(shape: TopoDS_Shape) -> bool: ...
def get_type_as_string(shape: TopoDS_Shape) -> str: ...
def get_sorted_hlr_edges(
    shape: TopoDS_Shape,
    position: Optional[gp_Pnt] = None,
    direction: Optional[gp_Dir] = None,
    export_hidden_edges: Optional[bool] = True,
) -> Tuple[List, List]: ...
def list_of_shapes_to_compound(
    list_of_shapes: List[TopoDS_Shape],
) -> Tuple[TopoDS_Compound, bool]: ...
